﻿#include <PlatformStruct.h>
#include "Sqlite3Store.h"
#include "../FacilityBaseLib/InstrumentData.h"
#include "../FacilityBaseLib/InstrumentInfo.h"
#include "../FacilityBaseLib/Container.h"
#include "../FacilityBaseLib/StringMgr.h"
#include "../FacilityBaseLib/DateTimeHelper.h"
#include <cassert>
#include <float.h>
#include "DataSql.h"
#ifdef WIN32
#include <direct.h>
#include <io.h>
#endif

#include "../ServiceLib/ServiceLib.h"
#include "../Log/logging.h"
#include <stdexcept>
#include <boost/make_shared.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>



typedef bool (*SqliteRowFunc) (sqlite3_stmt *stmt, void *data);

sqlite3_stmt *
	sqlite_query_prepare (sqlite3 *db, const char *sql)
{
	sqlite3_stmt *stmt=NULL;
	int result;

	result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);

	if (result != SQLITE_OK) {
		const char *str = sqlite3_errmsg (db);
        //throw sqlite_error(str ? str : "unknown error");

		return NULL;
	}

	return stmt;
}

int sqlite_query_exec (sqlite3 *db, const char *sql)
{
	char *errmsg = NULL;
	int result;

	result = sqlite3_exec (db, sql, NULL, NULL, &errmsg);

	if (result != SQLITE_OK) {
		if (errmsg != NULL) {
			sqlite3_free (errmsg);
		}
		return -1;
	}
	return 0;
}

int sqlite_foreach_selected_row (sqlite3 *db, const char *sql,
	SqliteRowFunc callback, void *data)
{
	sqlite3_stmt *stmt=NULL;
	int result;
	int n_rows = 0;

	stmt = sqlite_query_prepare(db, sql);
	if (!stmt) {
		return -1;
	}

	while (1) {
		result = sqlite3_step (stmt);
		
		if (result != SQLITE_ROW)
			break;
		
		if (callback && !callback (stmt, data))
			break;
		else
		{
			n_rows++;
		}
	}

	if (result == SQLITE_ERROR) {
		sqlite3_finalize (stmt);
		return -1;
	}

	sqlite3_finalize (stmt);
	return n_rows;
}

//加载合约信息的回调;

bool loadBasetableCB(sqlite3_stmt *stmt, void *data)
{
	InstrumentContainer *container = reinterpret_cast<InstrumentContainer *>(data);
	if (!container)
	{
		return false;
	}
	InstrumentInfo info;
	boost::shared_ptr<BASEDATA> pBaseData = boost::make_shared<BASEDATA>();
	BASEDATA& tempBasic=*pBaseData;

	strcpy(tempBasic.szCode , (const char *)sqlite3_column_text (stmt, 0));
	strcpy(tempBasic.szExchange  , (const char *)sqlite3_column_text (stmt, 1));
	strcpy(tempBasic.szName  , (const char *)sqlite3_column_text (stmt, 2));
	strcpy(tempBasic.ExchangeInstID  , (const char *)sqlite3_column_text (stmt, 3));
	strcpy(tempBasic.ProductID  , (const char *)sqlite3_column_text (stmt, 4));

	tempBasic.ProductClass  = sqlite3_column_int (stmt, 5);
	tempBasic.DeliveryYear = sqlite3_column_int (stmt, 6);
	tempBasic.DeliveryMonth = sqlite3_column_int (stmt, 7);
	tempBasic.MaxMarketOrderVolume = sqlite3_column_int (stmt, 8);
	tempBasic.MinMarketOrderVolume = sqlite3_column_int (stmt, 9);
	tempBasic.MaxLimitOrderVolume = sqlite3_column_int (stmt, 10);
	tempBasic.MinLimitOrderVolume = sqlite3_column_int (stmt, 11);
	tempBasic.VolumeMultiple = sqlite3_column_int (stmt, 12);
	tempBasic.PriceTick = sqlite3_column_double (stmt, 13);
	strcpy(tempBasic.CreateDate , (const char *)sqlite3_column_text (stmt, 14));
	strcpy(tempBasic.OpenDate , (const char *)sqlite3_column_text (stmt, 15));
	strcpy(tempBasic.ExpireDate , (const char *)sqlite3_column_text (stmt, 16));
	strcpy(tempBasic.StartDelivDate , (const char *)sqlite3_column_text (stmt, 16));
	strcpy(tempBasic.EndDelivDate , (const char *)sqlite3_column_text (stmt, 17));
	tempBasic.InstLifePhase = sqlite3_column_int (stmt, 18);
	tempBasic.IsTrading = sqlite3_column_int (stmt, 19);
	tempBasic.PositionType = sqlite3_column_int (stmt, 20);
	tempBasic.PositionDateType = sqlite3_column_int (stmt, 21);
	tempBasic.LongMarginRatio = sqlite3_column_int (stmt, 22);
	tempBasic.ShortMarginRatio = sqlite3_column_int (stmt, 23);
	info.set_id(tempBasic.szExchange,tempBasic.szCode);
	InstrumentInfo::update(info,pBaseData);
	if (info.is_valid())
	{
		container->add(info);
	}
	return true;
}

bool loadCodetableCB(sqlite3_stmt *stmt, void *data)
{
	InstrumentContainer *container = reinterpret_cast<InstrumentContainer *>(data);
	if (!container)
	{
		return false;
	}
	InstrumentInfo info;
	const char* szCode = (const char*)sqlite3_column_text(stmt, 0);
	const char* szExchange = (const char*)sqlite3_column_text(stmt, 1);

	info.set_id(szExchange,szCode);
	const char* szName = (const char*)sqlite3_column_text(stmt, 2);
	info.set_name(szName);

	info.set_type(sqlite3_column_int(stmt,3));

	info.SetShortName((const char*)sqlite3_column_text(stmt,4));

	info.SetNameEnu((const char*)sqlite3_column_text(stmt,5));

	if (info.is_valid())
	{
		container->add(info);
	}
	return true;
}

Sqlite3Store::Sqlite3Store(void)
	:IDataStore()
{
	mTickDB = nullptr;
	mInstDB = nullptr;
	mKdataDB = nullptr;
	mMinuteDB = nullptr;
	mNewsDB = nullptr;
}


Sqlite3Store::~Sqlite3Store(void)
{
	if (mTickDB)
	{
		sqlite3_close(mTickDB);
		mTickDB = nullptr;
	}
	if (mInstDB)
	{
		sqlite3_close(mInstDB);
		mInstDB = nullptr;
	}
	if (mKdataDB)
	{
		sqlite3_close(mKdataDB);
		mKdataDB = nullptr;
	}
	if (mMinuteDB)
	{
		sqlite3_close(mMinuteDB);
		mMinuteDB = nullptr;
	}
	if (mNewsDB)
	{
		sqlite3_close(mNewsDB);
		mNewsDB = nullptr;
	}
}


int Sqlite3Store::StoreBasetable( InstrumentContainer & container )
{
	if (!m_bIsOK)
	{
		return NONE;
	}
	container.lock();
	char* errmsg=NULL;

	//开始插入数据;
	int res = sqlite3_exec(mInstDB,sql_begin_transaction,0,0, &errmsg);
	size_t i=0;
	for (i=0;i<container.size();i++)
	{
		InstrumentInfo& info=container[i];
		if (strlen(info.ProductID)<=0)
		{
            strncpy(info.ProductID,info.szCode,sizeof(info.ProductID));
		}
		ostringstream sql_insert;
		sql_insert<<"replace into instruments values("
		<<"'"<<info.szCode<<"',"
		<<"'"<<info.szExchange<<"',"
		<<"'"<<info.szName<<"',"
		<<"'"<<info.ExchangeInstID<<"',"
		<<"'"<<info.ProductID<<"',"
		<<info.ProductClass<<","
		<<info.DeliveryYear<<","
		<<info.DeliveryMonth<<","
		<<info.MaxMarketOrderVolume<<","
		<<info.MinMarketOrderVolume<<","
		<<info.MaxLimitOrderVolume<<","
		<<info.MinLimitOrderVolume<<","
		<<info.VolumeMultiple<<","
		<<info.PriceTick<<","
		<<"'"<<info.CreateDate<<"',"
		<<"'"<<info.OpenDate<<"',"
		<<"'"<<info.ExpireDate<<"',"
		<<"'"<<info.StartDelivDate<<"',"
		<<"'"<<info.EndDelivDate<<"',"
		<<info.InstLifePhase<<","
		<<info.IsTrading<<","
		<<info.PositionType<<","
		<<info.PositionDateType<<","
		<<info.LongMarginRatio<<","
		<<info.ShortMarginRatio<<")";
		std::string sql_str=sql_insert.str();
		if(SQLITE_OK!=sqlite3_exec(mInstDB,sql_str.c_str(),NULL,NULL,&errmsg))
		{
			break;
		}
	}
	res = sqlite3_exec(mInstDB,sql_commit_transaction,0,0, &errmsg);
	container.unlock();
	return res ==  SQLITE_OK ? container.size(): -1 ;
}

int Sqlite3Store::StoreReport(std::vector<boost::shared_ptr<Tick> > pReport, bool bBigTrade)
{
	if (!m_bIsOK)
	{ 
		return 0;
	}
	if (pReport.size()<=0)
	{
		return 0;
	}
	int nReportCount = 0;
	char* errmsg=NULL;
	int res = sqlite3_exec(mTickDB,sql_begin_transaction,0,0, &errmsg);
	for (std::size_t i=0;i<pReport.size();++i)
	{
		if (!pReport[i])
		{
			continue;
		}
		std::string table_name=pReport[i]->szCode;
		
		std::string sql_create_report_table = boost::str(boost::format(sql_create_table_report) % table_name);

		int res_create_table = sqlite3_exec(mTickDB, sql_create_report_table.c_str(), NULL, NULL, &errmsg);
		if (res_create_table != SQLITE_OK)
		{
			continue;
		}
		ostringstream sqlBuf2;
		sqlBuf2<<"insert into "<<table_name<<" values('"
			<<pReport[i]->szCode<<"','"
			<< pReport[i]->szExchange << "','"
			<< pReport[i]->TradingDay << "',"
			<<(int64_t)pReport[i]->UpdateTime<<","
			<<pReport[i]->UpdateMillisec<<","
			<<pReport[i]->PreClosePrice<<","
			<<pReport[i]->OpenPrice<<","
			<<pReport[i]->ClosePrice<<","
			<<pReport[i]->HighestPrice<<","
			<<pReport[i]->LowestPrice<<","
			<<pReport[i]->LastPrice<<","
			<<pReport[i]->AveragePrice<<","
			<<pReport[i]->CurrDelta<<","
			<<pReport[i]->PreDelta<<","
			<<pReport[i]->PreSettlementPrice<<","
			<<pReport[i]->SettlementPrice<<","
			<<pReport[i]->UpperLimitPrice<<","
			<<pReport[i]->LowerLimitPrice<<","
			<<pReport[i]->OpenInterest<<","
			<<pReport[i]->Volume<<","
			<<pReport[i]->Turnover<<","
			<<pReport[i]->BidPrice[0]<<","
			<<pReport[i]->BidVolume[0]<<","
			<< pReport[i]->AskPrice[0] << ","
			<<pReport[i]->AskVolume[0]<<")";
		int exe_res=sqlite3_exec(mTickDB,sqlBuf2.str().c_str(),NULL,NULL,&errmsg);
		if (exe_res != SQLITE_OK)
		{
			LOGDEBUG("StoreReport error:{}",std::string(errmsg));
		}
		else
		{
			++nReportCount;
		}
	}
	res = sqlite3_exec(mTickDB,sql_commit_transaction,0,0, &errmsg);
	if (res != SQLITE_OK)
	{
		return -1;
	}
	LOGDEBUG("StoreReport Count:{}" , nReportCount);
	return nReportCount;
}



int Sqlite3Store::StoreMinute(std::vector<boost::shared_ptr<MINUTE> > pMinute)
{
	if (!m_bIsOK)
	{
		return 0;
	}
	//存储分时行情;
	char* errmsg=NULL;
	int res = sqlite3_exec(mMinuteDB,sql_begin_transaction,0,0, &errmsg);
	int nMinuteCount = 0;
	for (std::size_t i=0;i<pMinute.size();++i)
	{
		//1.构造表名;
		if (!pMinute[i])
		{
			continue;
		}
		std::string tableName=pMinute[i]->szCode;
		std::string sql_create_table = boost::str(boost::format(sql_create_minute) % tableName);
			
		int res_exec = sqlite3_exec(mMinuteDB, sql_create_table.c_str(), NULL, NULL, &errmsg);
		std::ostringstream insert_sql;
		insert_sql<<"insert into "<<tableName<<" values('"
			<< pMinute[i]->szCode<<"','"
			<< pMinute[i]->szExchange<<"','"
			<< pMinute[i]->szName<<"',"
			<< pMinute[i]->LastPrice<<","
			<< pMinute[i]->HighestPrice<<","
			<< pMinute[i]->LowestPrice<<","
			<< pMinute[i]->Volume<<","
			<< pMinute[i]->Turnover<<","
			<< pMinute[i]->TradingTime<<","
			<< pMinute[i]->TradingMillisec<<")";
		res_exec = sqlite3_exec(mMinuteDB,insert_sql.str().c_str(),NULL,NULL,&errmsg);
		if (res_exec == SQLITE_OK)
		{
			++nMinuteCount;
		}
	}
	res = sqlite3_exec(mMinuteDB,sql_commit_transaction,0,0, &errmsg);
	if (SQLITE_OK!=res)
	{
		return -1;
	}
	return nMinuteCount;
}



bool Sqlite3Store::CreateDB( const std::string& dbname,struct sqlite3*& db)
{
	if (dbname.empty())
	{
		return false;
	}
	//分时数据表;
	const char* errmsg=NULL;
	std::string db_path=std::string(m_szRootPath).append("/").append(dbname);
	if (SQLITE_OK!=sqlite3_open(db_path.c_str(),&db))
	{
		errmsg = sqlite3_errmsg (db);
		last_error_msg=(errmsg ? errmsg : "unknown error");
		return false;
	}
	return true;
}


//connect执行登录，只需要调用一次;
int Sqlite3Store::Init(const std::string& initStr )
{
	if (m_bIsOK)
	{
		return 0;
	}
	if (initStr.empty())
		return BAD_FIELD;

	//创建数据库目录;
	std::string	strRoot	= initStr;
	int nLen = strRoot.length();
	if (strRoot[nLen-1] != L'\\' && strRoot[nLen-1] != L'/')
		strRoot	+= CHAR_DIRSEP;
	nLen = strRoot.length();
	if (0 != access((strRoot  ).c_str(), 0))
	{
		if(0!=_mkdir((strRoot ).c_str()))
		{
			return NO_PRIVILEGE;
		}
	}
	strcpy(m_szRootPath,initStr.c_str());
	//Tick数据表;
	auto cur_year=boost::gregorian::day_clock::local_day().year();
	std::string dbname = boost::str(boost::format("%1%.db")%(cur_year));
	bool bCreated=CreateDB(dbname,mTickDB);
	if (!bCreated)
	{
		last_error_msg=dbname+":"+last_error_msg;
	}
	m_dbs.insert(std::pair<std::string,struct sqlite3*>(dbname,mTickDB));
	//基本信息数据库;
	dbname="instruments.db";
	bCreated=CreateDB(dbname,mInstDB);
	if (!bCreated)
	{
		last_error_msg=dbname+":"+last_error_msg;
	}
	m_dbs.insert(std::pair<std::string,struct sqlite3*>(dbname,mInstDB));
	//K线表;
	dbname="kdata.db";
	bCreated=CreateDB(dbname,mKdataDB);
	if (!bCreated)
	{
		last_error_msg=dbname+":"+last_error_msg;
	}
	m_dbs.insert(std::pair<std::string,struct sqlite3*>(dbname,mKdataDB));
	//分时数据表;
	dbname="minute.db";
	bCreated=CreateDB(dbname,mMinuteDB);
	if (!bCreated)
	{
		last_error_msg=dbname+":"+last_error_msg;
	}
	m_dbs.insert(std::pair<std::string,struct sqlite3*>(dbname,mMinuteDB));
	dbname = "news.db";
	bCreated = CreateDB(dbname, mNewsDB);
	if (!bCreated)
	{
		last_error_msg = dbname + ":" + last_error_msg;
	}
	m_dbs.insert(std::pair<std::string, struct sqlite3*>(dbname, mNewsDB));
	m_bIsOK=CreateTables();
	return m_bIsOK?NONE:NOT_LOGIN_YET;
}


int Sqlite3Store::Release()
{
	if (!m_bIsOK)
	{
		return 0;
	}
	try
	{
		if (mTickDB)
		{
			const char* errmsg=NULL;
			if(SQLITE_OK!=sqlite3_close(mTickDB))
			{
				errmsg = sqlite3_errmsg (mTickDB);
                throw sqlite_error( errmsg ? errmsg : "unknown error");
			}
			mTickDB=NULL;
		}
		m_bIsOK=false;
	}catch(std::exception& p)
	{
		last_error_msg=(char*)(p.what());
		//LOGDEBUG("Sqlite3Operator::Release异常:%s",p.what());
		return -1;
	}
	return 1;
}

int Sqlite3Store::IsDataSetExists(std::string tableName )
{
	
	return IsDataSetExists(tableName,mTickDB);
}

bool Sqlite3Store::IsDataSetExists( const std::string& tbname,struct sqlite3* db )
{
	if (!m_bIsOK)
	{
		return false;
	}
	try{
		std::string sql="select count(*) as 'count' from sqlite_master where type ='table' and name = '";
		sql+=tbname;
		sql+="'";
		sqlite3_stmt *stmt=NULL;
		stmt = sqlite_query_prepare (db, sql.c_str());
		if (!stmt) {
			return false;
		}
		int result = sqlite3_step (stmt);
		if (result!=SQLITE_ROW)
		{
			return false;
		}
		int nRows=sqlite3_column_int(stmt,0);
		return nRows>0;
	}catch (std::exception& p)
	{
		last_error_msg=(char*)(p.what());
		//LOGDEBUG("Sqlite3Operator::IsDataSetExists异常:%s",p.what());
		return false;
	}
	return false;

}


int Sqlite3Store::SetOptions( int optionType,int optionValue )
{
	auto oIter = m_Options.find(optionType);
	if (oIter== m_Options.end())
	{
		m_Options.insert(std::make_pair(optionType,optionValue));
		return 0;
	}
	else
	{
		return oIter->second;
	}
}
//注意，是取得所有的字段名称;
std::vector<std::string> Sqlite3Store::GetDataSetFieldNames( std::string setName )
{
	std::vector<std::string> fieldNames;
	try{
		std::string sql="select * from sqlite_master where type='table' and name='";
		sql+=setName;
		sql+="'";

		sqlite3_stmt *stmt=NULL;
		int result=0;
		int n_rows = 0;

		if (SQLITE_OK!=sqlite3_prepare(mTickDB, sql.c_str(), -1,&stmt,NULL)) {
			return fieldNames;
		}

		while (1) {
			result = sqlite3_step (stmt);
			if (result != SQLITE_ROW)
				break;
			n_rows++;
			const char *fieldName = (const char *)sqlite3_column_text (stmt, 0);
			fieldNames.push_back(fieldName);
		}

		if (result == SQLITE_ERROR) {
			const char *s = sqlite3_errmsg (mTickDB);

            throw sqlite_error(s ? s : "no error given");
			sqlite3_finalize (stmt);
			return fieldNames;
		}

		sqlite3_finalize (stmt);
    }catch(sqlite_error& p)
	{
		last_error_msg=(char*)p.what();
	}
	return fieldNames;
}

//pInstrument至少应当包含合约代码;

//加载公钟K线数据;
bool loadKDataCB (sqlite3_stmt *stmt, void *data)
{
	if (!stmt)
	{
		return false;
	}
	KdataContainer* pInstrument=reinterpret_cast<KdataContainer*>(data);
	if (!pInstrument)
	{
		return false;
	}
	KDATA tempKData;
	strcpy(tempKData.szCode,(const char*)sqlite3_column_text(stmt,0));
	strcpy(tempKData.szExchange,(const char*)sqlite3_column_text(stmt,1));
	
	tempKData.OpenPrice=sqlite3_column_double(stmt,2);
	tempKData.HighestPrice=sqlite3_column_double(stmt,3);
	tempKData.LowestPrice=sqlite3_column_double(stmt,4);
	
	
	tempKData.ClosePrice=sqlite3_column_double(stmt,5);

	tempKData.Volume=sqlite3_column_int64(stmt,6);
	tempKData.Turnover=sqlite3_column_double(stmt,7);

	tempKData.AveragePrice=sqlite3_column_double(stmt,8);

	tempKData.PreClosePrice=sqlite3_column_double(stmt,9);
	
	tempKData.TradingTime=sqlite3_column_int(stmt,10);

	strcpy(tempKData.TradingDay, (const char*)sqlite3_column_text(stmt, 11));

	pInstrument->push_back(tempKData);

	return true;
}


//通过SQL语句来控制获取的K线数据;
int Sqlite3Store::LoadKData(InstrumentData* pInstrument, int nKType, int nLength)
{
	//2种办法查询表后面的N行;
	//SELECT InstrumentID, TradingTime, TradingDay from ni1805_kdmin1 LIMIT 20 offset(SELECT CASE WHEN COUNT(*) > 20 THEN COUNT(*) - 20 ELSE 0 END  FROM ni1805_kdmin1)

	//SELECT * FROM(SELECT InstrumentID, TradingTime, TradingDay from ni1805_kdmin1 ORDER BY TradingTime DESC  LIMIT 20) ORDER BY TradingTime ASC
	//将原来的数据清空;
	KdataContainer& kdatas = pInstrument->GetKData(nKType);
	kdatas.Clear();
	//1.表名;
	//判断日线表是否存在;
	std::string tablename=GetKDataTableName(pInstrument->GetInstrumentID(),nKType);
	int nKDataSize=0;
	if (IsDataSetExists(tablename,mKdataDB))
	{
		//K线数据表存在,表存在,从里面取数据;
		//取出开盘价，收盘价，最高价，最低价，成交量总全，成交额总和;
		std::string sql=boost::str(boost::format("SELECT InstrumentID,ExchangeID,OpenPrice,HighestPrice,LowestPrice,"
			"ClosePrice,Volume,Turnover,AveragePrice,PreClosePrice,TradingTime,TradingDay from %1% where InstrumentID ='%2%' "
			" ORDER BY TradingTime %3% ")
		%tablename%pInstrument->GetInstrumentID() % (nLength >= 0 ? "DESC" : "ASC"));
		if (nLength > 0)
		{
			sql += (std::string(" LIMIT ") + std::to_string(nLength));
		}
		std::string msql = boost::str(boost::format("SELECT * FROM (%1%) ORDER BY TradingTime %2% ") % sql % (nLength >= 0 ? "ASC" : "DESC"));
		sqlite_foreach_selected_row(mKdataDB, msql.c_str(), loadKDataCB, &kdatas);
		nKDataSize = kdatas.size();
		return nKDataSize;
	}
	else
	{
		switch (nKType)
		{
		case ktypeMin:   // 1分钟K线;
			{
				LoadReport(pInstrument, nLength);
				KdataContainer kds;
				kds.SetKType(nKType);
				nKDataSize = pInstrument->GetReport().ToKData(kds);
				//合并数据;
				pInstrument->GetKData(nKType).MergeKData(&kds);
				break;
			}
		case ktypeDay:
			{
				//日线从15分钟线转;
				int nSubKDataSize = LoadKData(pInstrument, ktypeMin, nLength);
				if (nSubKDataSize>0)
				{
					nKDataSize=KdataContainer::Min1ToDay(pInstrument->GetKData(ktypeMin),pInstrument->GetKData(ktypeDay));
				}
			}
			break;
		case ktypeWeek:
			{
				int nSubKDataSize = LoadKData(pInstrument, ktypeDay, nLength);
				if (nSubKDataSize>0)
				{
					nKDataSize = KdataContainer::DayToWeek(pInstrument->GetKData(ktypeDay), pInstrument->GetKData(ktypeWeek));
				}
			}
			break;
		case ktypeMonth:
			{
				//从日线转;
				int nSubKDataSize=LoadKData(pInstrument,ktypeDay);
				if (nSubKDataSize>0)
				{
					nKDataSize=KdataContainer::DayToMonth(pInstrument->GetKData(ktypeDay),pInstrument->GetKData(ktypeMonth));
				}
			}
			break;
		case ktypeSeason:
		case ktypeYear:
			{
				//从月线转;

				return 0;
			}
			break;
		default:
			{
				//如果K线小于1分钟,从Tick转;
				if (nKType<ktypeMin)
				{
					//周期小于1分钟;
					LoadReport(pInstrument);
					nKDataSize= pInstrument->GetReport().ToKData(pInstrument->GetKData(nKType));
				}
				else if (nKType>ktypeMin && nKType <=ktypeMin60*6)
				{
					//周期小于6小时的K线，都从1分钟线转;
					if (nKType%ktypeMin60==0)
					{
						//从60分钟线转;
						int nSubKDataSize = LoadKData(pInstrument, ktypeMin30, nLength);
						if (nSubKDataSize>0)
						{
							nKDataSize=KdataContainer::ConvertKData(pInstrument->GetKData(ktypeMin30),
								pInstrument->GetKData(nKType), nKType / ktypeMin30);
						}
					}
					else if (nKType%ktypeMin30==0)
					{
						//从30分钟数据转;
						int nSubKDataSize = LoadKData(pInstrument, ktypeMin15, nLength);
						if (nSubKDataSize>0)
						{
							nKDataSize=KdataContainer::ConvertKData(pInstrument->GetKData(ktypeMin15),
								pInstrument->GetKData(nKType), nKType / ktypeMin15);
						}
					}
					else if(nKType%ktypeMin15==0)
					{
						//从15分钟数据转;
						int nSubKDataSize=LoadKData(pInstrument,ktypeMin5,nLength);
						if (nSubKDataSize>0)
						{
							nKDataSize=KdataContainer::ConvertKData(pInstrument->GetKData(ktypeMin5),
								pInstrument->GetKData(nKType), nKType / ktypeMin5);
						}
					}
					else if (nKType%ktypeMin5==0)
					{
						//从5分钟数据转;
						int nSubKDataSize = LoadKData(pInstrument, ktypeMin, nLength);
						if (nSubKDataSize>0)
						{
							nKDataSize=KdataContainer::ConvertKData(pInstrument->GetKData(ktypeMin),
								pInstrument->GetKData(nKType),nKType/ktypeMin);
						}
					}
					else
					{
						//从1分钟数据转;
						int nSubKDataSize = LoadKData(pInstrument, ktypeMin, nLength);
						if (nSubKDataSize>0)
						{
							nKDataSize=KdataContainer::ConvertKData(pInstrument->GetKData(ktypeMin),
								pInstrument->GetKData(nKType),nKType/ktypeMin);
						}
					}
				}
				else if ( ktypeDay>= nKType && nKType<=ktypeMonth)
				{
					//周期在30天以内的都从日线转;
				}
			}
			break;
		}
		StoreKData(pInstrument->GetKData(nKType),true);
	}
	return nKDataSize;
}


//从合约表中查询合约的基本信息;
//还要从其他表中查询合约的其他信息;
int Sqlite3Store::LoadBaseText( InstrumentData* pInstrument )
{
	if (!m_bIsOK)
	{
		return NOT_INITED;
	}
	try{
		std::string id=pInstrument->GetInstrumentID();
		std::string sql="SELECT InstrumentID,InstrumentName,Instruments.ExchangeID,ExchangeInstID,ExchangeName,ExchangeProperty,"
			"ProductID,ProductClass,DeliveryYear,DeliveryMonth,MaxMarketOrderVolume,MinMarketOrderVolume,MaxLimitOrderVolume,"
			"MinLimitOrderVolume,VolumeMultiple,PriceTick,CreateDate,OpenDate,ExpireDate,StartDelivDate,EndDelivDate,"
			"InstLifePhase,IsTrading,PositionType,PositionDateType,LongMarginRatio,ShortMarginRatio FROM Instruments,"
			"Exchanges WHERE Instruments.ExchangeID=Exchanges.ExchangeID AND InstrumentID='";
		sql+=pInstrument->GetInstrumentID();
		sql+="'";
		sqlite_foreach_selected_row(mInstDB,sql.c_str(),loadBasetableCB,pInstrument);
	}catch(std::exception& p){ 
		last_error_msg=(char*)p.what();
		return -1;
	}
	return 1;
}
/**
 * \brief 获取分时行情数据;
 *
 */
bool loadMinuteCB(sqlite3_stmt *stmt, void *data)
{
	if (!stmt)
	{
		return false;
	}
	InstrumentData* pInstrument=reinterpret_cast<InstrumentData*>(data);
	if (!pInstrument)
	{
		return false;
	}
	MINUTE tempMinute;
	tempMinute.Type = 1;
	strcpy(tempMinute.szCode,(const char*)sqlite3_column_text(stmt,0));
	strcpy(tempMinute.szExchange,(const char*)sqlite3_column_text(stmt,1));
	strcpy(tempMinute.szName,(const char*)sqlite3_column_text(stmt,2));

	tempMinute.LastPrice=sqlite3_column_double(stmt,3);
	
	tempMinute.LowestPrice=sqlite3_column_double(stmt,4);
	tempMinute.HighestPrice=sqlite3_column_double(stmt,5);

	tempMinute.Volume=sqlite3_column_int64(stmt,6);
	tempMinute.Turnover=sqlite3_column_double(stmt,7);
	tempMinute.TradingTime=sqlite3_column_int(stmt,8);
	tempMinute.TradingMillisec=sqlite3_column_int(stmt,9);
	pInstrument->GetMinute().push_back(tempMinute);
	return true;
}
int Sqlite3Store::LoadMinute(InstrumentData* pInstrument, int nLength )
{
	if (!m_bIsOK)
	{
		return NOT_INITED;
	}
	//1.如果分时表存在，则直接从分时表里取数据;
	if (IsDataSetExists(pInstrument->GetInstrumentID(), mMinuteDB))
	{
		//读取分时数据;
		//最新价:一分钟里的最后一个tick数据;
		std::string sql=boost::str(boost::format("select InstrumentID,ExchangeID,InstrumentName, LastPrice,"
			"LowestPrice,HighestPrice,Volume,Turnover,UpdateTime,UpdateMillisec  from %1% " 
			" ORDER BY UpdateTime %2%,UpdateMillisec %2% ") % pInstrument->GetInstrumentID() % (nLength >= 0 ? "DESC" : "ASC") );
		if (nLength > 0)
		{
			sql+=(std::string(" LIMIT ") + std::to_string(nLength));
		}
		std::string msql = boost::str(boost::format("SELECT * FROM (%1%) ORDER BY UpdateTime %2% , UpdateMillisec %2% ")
			% sql % (nLength >= 0 ? "ASC" : "DESC"));
		sqlite_foreach_selected_row(mMinuteDB,msql.c_str(),loadMinuteCB,pInstrument);
	}
	else
	{
		//2.如果分时表不存在,则从实时行情里面取数据;
		LoadReport(pInstrument,nLength);
		//把Tick数据转换成分时数据;
		ReportContainer& rpt_containter=pInstrument->GetReport();
		MINUTE	minute = {0};

		//过滤掉集合竞价时间;
		auto auctionMatchTime = DateTimeHelper::GetInstance().GetAuctionMatchTime(pInstrument->GetInstrumentID());

		for (std::size_t i=0;i<rpt_containter.size();++i)
		{
			auto ptAuctionBegin = boost::posix_time::duration_from_string(auctionMatchTime.first);
			auto ptAuctionEnd = boost::posix_time::duration_from_string(auctionMatchTime.second);
			auto ptReportTime = boost::posix_time::duration_from_string(rpt_containter[i].UpdateTimeStr);
			if ((ptReportTime >= ptAuctionBegin) && (ptReportTime < ptAuctionEnd))
			{
				continue;
			}
			if( convert_REPORT_to_MINUTE( &rpt_containter[i], &minute ) )
			{
				pInstrument->GetMinute().InsertMinuteSort(minute);
			}
		}
	}
	return pInstrument->GetMinute().size();
}

bool loadReportCB(sqlite3_stmt *stmt, void *data)
{
	if (!stmt)
	{
		return false;
	}
	InstrumentData* pInstrument = reinterpret_cast<InstrumentData *>(data);
	if (!pInstrument)
	{
		return false;
	}
	Tick tempReport;
	memset(&tempReport,0,sizeof(Tick));
	strcpy(tempReport.szCode,(const char*)sqlite3_column_text(stmt,0));
	strcpy(tempReport.szExchange, (const char*)sqlite3_column_text(stmt, 1));
	tempReport.UpdateMillisec=sqlite3_column_int(stmt,2);
	tempReport.UpdateTime=sqlite3_column_int64(stmt,23);
	strcpy(tempReport.TradingDay, (const char*)sqlite3_column_text(stmt, 24));

	boost::posix_time::ptime pRptTime = boost::posix_time::from_time_t(tempReport.UpdateTime);
	if (pRptTime <= pInstrument->m_ptEnd && pRptTime > pInstrument->m_ptBegin)
	{
		tempReport.PreClosePrice = sqlite3_column_double(stmt, 3);
		tempReport.OpenPrice = sqlite3_column_double(stmt, 4);
		tempReport.ClosePrice = sqlite3_column_double(stmt, 5);
		tempReport.HighestPrice = sqlite3_column_double(stmt, 6);
		tempReport.LowestPrice = sqlite3_column_double(stmt, 7);
		tempReport.LastPrice = sqlite3_column_double(stmt, 8);
		tempReport.AveragePrice = sqlite3_column_double(stmt, 9);
		tempReport.CurrDelta = sqlite3_column_double(stmt, 10);
		tempReport.PreDelta = sqlite3_column_double(stmt, 11);
		tempReport.PreSettlementPrice = sqlite3_column_double(stmt, 12);
		tempReport.SettlementPrice = sqlite3_column_double(stmt, 13);
		tempReport.UpperLimitPrice = sqlite3_column_double(stmt, 14);
		tempReport.LowerLimitPrice = sqlite3_column_double(stmt, 15);
		tempReport.OpenInterest = sqlite3_column_double(stmt, 16);
		tempReport.Volume = sqlite3_column_int64(stmt, 17);
		tempReport.Turnover = sqlite3_column_double(stmt, 18);
		tempReport.BidPrice[0] = sqlite3_column_double(stmt, 19);
		tempReport.BidVolume[0] = sqlite3_column_int(stmt, 20);
		tempReport.AskPrice[0] = sqlite3_column_double(stmt, 21);
		tempReport.AskVolume[0] = sqlite3_column_int(stmt, 22);

		//strcpy(tempReport.TradingDay, boost::gregorian::to_iso_string(pRptTime.date()).c_str());
		strcpy(tempReport.UpdateTimeStr, boost::posix_time::to_simple_string(pRptTime.time_of_day()).c_str());
		if (pInstrument->GetReport().size() > 0)
		{
			Tick& prevTick = pInstrument->GetReport().back();
			boost::posix_time::ptime prevTickTime = boost::posix_time::from_time_t(prevTick.UpdateTime);
			prevTickTime += boost::posix_time::milliseconds(prevTick.UpdateMillisec);
			pRptTime += boost::posix_time::milliseconds(tempReport.UpdateMillisec);
			if (prevTickTime >= pRptTime)
			{
				//前一行的时间，比当前行的时间还要大,则替换掉;
				prevTick = tempReport;
			}
			else
			{
				pInstrument->GetReport().push_back(tempReport);
			}
		}
		else
		{
			pInstrument->GetReport().push_back(tempReport);
		}
	}
	return true;
}
/**
 * \brief 取得分时行情的详细数据;
 *
 */
int Sqlite3Store::LoadReport(InstrumentData* pInstrument, int nLength)
{
	if (!m_bIsOK)
	{
		return NOT_INITED;
	}
	auto cur_year = boost::gregorian::day_clock::local_day().year();
	std::string dbname = std::to_string(cur_year) + ".db";
	struct sqlite3* yearDB=NULL;
	auto dbiter=m_dbs.find(dbname);
	if (dbiter!=m_dbs.end())
	{
		//该数据库已经打开;
		yearDB=dbiter->second;
	}
	else
	{
		if(CreateDB(dbname.c_str(),yearDB))
		{
			m_dbs.insert(std::pair<std::string,struct sqlite3*>(dbname.c_str(),yearDB));
		}
	}
	std::string table_name=pInstrument->GetInstrumentID();
	if (yearDB)
	{
		std::string sql=boost::str(boost::format("SELECT InstrumentID,ExchangeID,TradingMillisec,PreClosePrice,"
			"OpenPrice,ClosePrice,HighestPrice,LowestPrice,LastPrice,AveragePrice,CurrDelta,PreDelta,"
			"PreSettlementPrice,SettlementPrice,UpperLimitPrice,LowerLimitPrice,OpenInterest,"
			"Volume,Turnover,BidPrice1,BidVolume1,AskPrice1,AskVolume1,TradingTime,TradingDay FROM %1% "
			" ORDER BY TradingTime %2%,TradingMillisec %2% ")%table_name%(nLength>=0?"DESC":"ASC"));
		if (nLength > 0)
		{
			sql+=(std::string(" LIMIT ")+std::to_string(nLength));
		}
		std::string msql=boost::str(boost::format("SELECT * FROM (%1%) ORDER BY TradingTime %2% , TradingMillisec %2% ")
			%sql%(nLength>=0?"ASC":"DESC"));
		
		sqlite3_stmt *statement=NULL;
		if ( sqlite3_prepare(yearDB,msql.c_str(), -1, &statement, 0 ) == SQLITE_OK ) 
		{
			int res = 0;
			while ( true )
			{
				res = sqlite3_step(statement);
				if ( res == SQLITE_ROW ) 
				{
					loadReportCB(statement,pInstrument);
				}
				if ( res == SQLITE_DONE )	
				{
					break;
				}
			}
		}
	}
	return pInstrument->GetReport().size();
}



//将时分秒转换为秒;
//hh:mm:ss时间;
//YYYYMMDD日期;
// time_t Sqlite3Store::ConvertTime2Seconds(std::string strDay, std::string strTime )
// {
// 	char hour[4];
// 	char minute[4];
// 	char second[4];
// 	char YYYY[6];
// 	char MM[4];
// 	char DD[4];
//     strncpy(YYYY,strDay.c_str(),4);
//     strncpy(MM,strDay.c_str()+4,2);
//     strncpy(DD,strDay.c_str()+6,2);
// 
//     strncpy(hour,strTime.c_str(),2);
//     strncpy(minute,strTime.c_str()+3,2);
//     strncpy(second,strTime.c_str()+6,2);
// 
// 	struct tm s_tm={0};
// 	s_tm.tm_year=atoi(YYYY)-1900;
// 	s_tm.tm_mon=atoi(MM)-1;
// 	s_tm.tm_mday=atoi(DD);
// 
// 	s_tm.tm_hour=atoi(hour);
// 	s_tm.tm_min=atoi(minute);
// 	s_tm.tm_sec=atoi(second);
// 	DateTime t(atoi(YYYY),atoi(MM),atoi(DD),atoi(hour),atoi(minute),atoi(second));
// 	return t.GetTime();
// }


int Sqlite3Store::LoadBasetable( InstrumentContainer& container )
{
	if (!m_bIsOK)
	{
		return 0;
	}
	//合约表是否存在?;
	std::string sql="select * from instruments";
	sqlite_foreach_selected_row(mInstDB,sql.c_str(),loadBasetableCB,&container);
	return container.size();
}
/**
 * \brief 取得根据数集的名称;
 * \remark 这个函数使用了ODBCAPI;
 */
std::string Sqlite3Store::GetRootDataSetName()
{
	return m_szRootPath;
}

int Sqlite3Store::InstallNewsText( const char * buffer, int nLen, const char *orgname )
{

	return 0;
}

int Sqlite3Store::InstallNewsText( const char * filename, const char *orgname )
{
	return 0;
}


int Sqlite3Store::InstallBaseText( const char * buffer, int nLen, const char *orgname )
{
	return 0;
}

int Sqlite3Store::InstallBaseText( const char * filename, const char *orgname )
{
	return 0;
}



int Sqlite3Store::InstallBasetable( const char * filename, const char *orgname )
{
	return 0;
}


int Sqlite3Store::InstallKData( KdataContainer & kdata, bool bOverwrite /*= FALSE */ )
{
	int nInsertCount = 0;
	if (!m_bIsOK)
	{
		return nInsertCount;
	}
	if (kdata.size()<=0)
	{
		return nInsertCount;
	}

	switch(kdata.GetKType())
	{
	case ktypeMin:
	case ktypeMin5:
	case ktypeMin15:
	case ktypeMin30:
	case ktypeMin60:
	case ktypeWeek:
	case ktypeDay:
	case  ktypeMonth:
	case  ktypeYear:
		{
			char* errmsg = NULL;
			std::string table_name = GetKDataTableName(kdata[0].szCode, kdata.GetKType());
			if (bOverwrite)
			{
				//覆盖数据;
				std::string sql_delete = boost::str(boost::format("delete from %1%") % table_name);
				if (SQLITE_OK != sqlite3_exec(mKdataDB, sql_delete.c_str(), NULL, NULL, &errmsg))
				{
					LOGDEBUG("cant clear kdata table:{}", table_name,errmsg);
				}
			}
			std::string create_sql = boost::str(boost::format(
				"create table if not exists %1%(kid INTEGER PRIMARY KEY AUTOINCREMENT,"
				"InstrumentID char(31),ExchangeID char(31),TradingDay char(9),"
				"OpenPrice double,HighestPrice double,LowestPrice double,"
				"ClosePrice double,Volume BIGINT,Turnover double,AveragePrice double,"
				"PreClosePrice double,TradingTime int)") %table_name);
			
			if (SQLITE_OK != sqlite3_exec(mKdataDB, create_sql.c_str(), NULL, NULL, &errmsg))
			{
				LOGDEBUG("cant create kdata table:{}",table_name);
				return nInsertCount;
			}

			//开始插入数据;
			int res = sqlite3_exec(mKdataDB,"begin transaction;",0,0, &errmsg);
			for (size_t i=0;i<kdata.size();i++)
			{
				KDATA& kd=kdata.at(i);
				ostringstream sql_insert;
				auto kdTime = boost::posix_time::from_time_t(kd.TradingTime);
				std::string timeStr=boost::posix_time::to_iso_string(kdTime);
				sql_insert<<"insert into "<<table_name<<" values(NULL,'"
				<<kd.szCode<<"','"<<kd.szExchange<<"','"<<kd.TradingDay<<"',"
					<<kd.OpenPrice<<","<<kd.HighestPrice<<","<<kd.LowestPrice<<","
					<<kd.ClosePrice<<","<<kd.Volume<<","<<kd.Turnover<<","
					<<kd.AveragePrice<<","<<kd.PreClosePrice<<","<<kd.TradingTime<<")";
				std::string sql=sql_insert.str();
				if (SQLITE_OK == sqlite3_exec(mKdataDB, sql.c_str(), NULL, NULL, &errmsg))
				{
					++nInsertCount;
				}
			}
			res = sqlite3_exec(mKdataDB,"commit transaction;",0,0, &errmsg);
		}
		break;
	default:
		break;
	}
	return nInsertCount;
}


int Sqlite3Store::InstallCodetblBlock( const char * filename, const char *orgname )
{
	return 0;
}

int Sqlite3Store::InstallCodetbl( const char * filename, const char *orgname )
{
	return 0;
}

int Sqlite3Store::StoreOutline(std::vector<boost::shared_ptr<OUTLINE> > pOutline)
{
	return 0;
}

int Sqlite3Store::LoadOutline( InstrumentData *pstock )
{
	return 0;
}

int Sqlite3Store::StoreDRData( InstrumentData *pstock )
{
	return 0;
}

int Sqlite3Store::LoadDRData( InstrumentData *pstock )
{
	return 0;
}

int Sqlite3Store::LoadKDataCache(InstrumentContainer &container, PROGRESS_CALLBACK fnCallback, void *cookie, int nProgStart, int nProgEnd)
{
	int nCount = 0;
	for (size_t i = 0; i < container.size();++i)
	{
		InstrumentInfo& info = container.at(i);
		KdataContainer& kdatas = info.m_kdata;
		kdatas.Clear();
		//1.表名;
		//判断日线表是否存在;
		std::string tablename = GetKDataTableName(info.get_id(), ktypeDay);
		int nLength = 1;
		if (IsDataSetExists(tablename, mKdataDB))
		{
			//K线数据表存在,表存在,从里面取数据;
			//取出开盘价，收盘价，最高价，最低价，成交量总全，成交额总和;
			std::string sql = boost::str(boost::format("SELECT InstrumentID,ExchangeID,OpenPrice,HighestPrice,LowestPrice,"
				"ClosePrice,Volume,Turnover,AveragePrice,PreClosePrice,TradingTime,TradingDay from %1% where TradingDay=(SELECT TradingDay from %1%) "
				" ORDER BY TradingTime %2% ")
				% tablename% (nLength >= 0 ? "DESC" : "ASC"));
			if (nLength > 0)
			{
				sql += (std::string(" LIMIT ") + std::to_string(nLength));
			}
			std::string msql = boost::str(boost::format("SELECT * FROM (%1%) ORDER BY TradingTime %2% ") % sql % (nLength >= 0 ? "ASC" : "DESC"));
			sqlite_foreach_selected_row(mKdataDB, msql.c_str(), loadKDataCB, &kdatas);
			int nKDataSize = kdatas.size();
			if (nKDataSize>0)
			{
				++nCount;
			}
		}
	}
	return nCount;
}

int Sqlite3Store::StoreCodetable( InstrumentContainer & container )
{
	if (!m_bIsOK)
	{
        return NOT_INITED;
	}
	container.lock();
	char* errmsg = NULL;
	//开始插入数据;
	int res = sqlite3_exec(mInstDB, sql_begin_transaction, 0, 0, &errmsg);
	size_t i = 0;
	for (i = 0; i < container.size(); i++)
	{
		InstrumentInfo& info = container[i];
		if (strlen(info.ProductID) <= 0)
		{
			strncpy(info.ProductID, info.szCode, sizeof(info.szCode));
		}
		std::ostringstream sql_insert;
		sql_insert << "replace into code_table values("
			<< "'" << info.szCode << "',"
			<< "'" << info.get_name() << "',"
			<< "'" << info.get_type() << "',"
			<< "'" << info.GetShortName() << "',"
			<< "'" << info.GetNameEnu() << "')";
		std::string sql_str = sql_insert.str();
		if (SQLITE_OK != sqlite3_exec(mInstDB, sql_str.c_str(), NULL, NULL, &errmsg))
		{
			break;
		}
	}
	res = sqlite3_exec(mInstDB, sql_commit_transaction, 0, 0, &errmsg);
	container.unlock();
	return res == SQLITE_OK ? container.size():-1;
}

int Sqlite3Store::GetMaxNumber()
{

	return 0;
}

bool Sqlite3Store::GetLastErrorMessage( char* lpszError, UINT nMaxError )
{
	if (NULL==lpszError)
	{
		return false;
	}
	strncpy(lpszError,last_error_msg.c_str(),nMaxError);
	return true;
}

DWORD Sqlite3Store::GetSelfTempPath( char *szTempPath, int size )
{
	strncpy(szTempPath, m_szRootPath, size);
	return 0;
}

int Sqlite3Store::LoadCodetable( InstrumentContainer &container )
{
	if (!m_bIsOK)
	{
		return 0;
	}
	//合约表是否存在?;
	std::string sql = "select * from code_table;";
	sqlite_foreach_selected_row(mInstDB, sql.c_str(), loadCodetableCB, &container);
	return container.size();
}

int Sqlite3Store::GetDBTypeInfo(std::string& dbtypeName/* =string */)
{
	dbtypeName="Sqlite3";
	return IDataStore::dbtypeSqlite3;
}

bool Sqlite3Store::GetFileName( std::string &sFileName, int nDataType, InstrumentInfo * pInfo /*= NULL*/, int nKType /*= ktypeDay */ )
{

	return false;
}

int Sqlite3Store::StoreKData( KdataContainer & kdata, bool bOverwrite /*= false */ )
{
	return InstallKData(kdata,bOverwrite);
}

int Sqlite3Store::StoreExchange(ExchangeContainer& exchanges )
{
	if (!m_bIsOK)
	{
		return 0;
	}
	int iRet=-1;
	char* errmsg=NULL;
	//开始插入数据;
	int res = sqlite3_exec(mInstDB, sql_begin_transaction, 0, 0, &errmsg);
	size_t i=0;
	char sql[256]={0};
	for (i=0;i<exchanges.size();i++)
	{
		auto exchange=exchanges[i];
		sprintf(sql,"replace into exchanges values('%s','%s',%d)",
			exchange->get_exchange_id().c_str(),
			exchange->get_exchange_name().c_str(),exchange->get_exchange_property());
		//sql<<"replace into exchanges values('"<<exchange.ExchangeID<<"','"<<exchange.ExchangeName<<"',"<<exchange.ExchangeProperty+");";
		std::string sql_str=sql;
		res = sqlite3_exec(mInstDB,sql,0,0, &errmsg);
		if (res != SQLITE_OK)  
		{  
            break;
		}
	}
	res = sqlite3_exec(mInstDB, sql_commit_transaction, 0, 0, &errmsg);
	iRet=i;
	return iRet;
}


bool loadExchangeCB(sqlite3_stmt* stmt,void* data)
{
	if (!stmt)
	{
		return false;
	}
	ExchangeContainer* pExchanges=reinterpret_cast<ExchangeContainer* >(data);
	if (!pExchanges)
	{
		return false;
	}
	exchange_t exchg{};
	strcpy(exchg.ExchangeID,(const char*)sqlite3_column_text(stmt,0));
	strcpy(exchg.ExchangeName,(const char*)sqlite3_column_text(stmt,1));
	exchg.ExchangeProperty=sqlite3_column_int(stmt,2);
	boost::shared_ptr<ExchangeBase> pexchange=boost::make_shared<ExchangeBase>(exchg);
	pExchanges->push_back(pexchange);
	return true;
}

int Sqlite3Store::LoadExchange(ExchangeContainer& exchanges )
{
	if (!m_bIsOK)
	{
		return 0;
	}
	//DateTime currTime=DateTime::current_time();//由pInstrument传一个时间过来;
	const char* sql="select ExchangeID,ExchangeName,ExchangeProperty from exchanges";
	sqlite_foreach_selected_row(mInstDB,sql,loadExchangeCB,&exchanges);
	return 1;
}

std::string Sqlite3Store::GetKDataTableName(const std::string& inst_id, int ktype )
{
	auto table_name_fmt = boost::format("%1%_%3%%2%") ;
	if (ktype<ktypeMin)
	{
		//小于1分钟的K线数据;
		return boost::str(table_name_fmt % inst_id % ktype % "kdsec");
	}
	else if (ktype>=ktypeMin && ktype<=ktypeMin60)
	{
		//分钟或者1小时K线;
		return boost::str(table_name_fmt % inst_id % (ktype/ktypeMin) % "kdmin");
	}
	else if(ktype>ktypeMin60 && ktype<ktypeDay)
	{
		//分钟或者1小时K线;
		return boost::str(table_name_fmt % inst_id % (ktype/ktypeMin60) % "kdhour");
	}
	else if(ktype>=ktypeDay && ktype<=ktypeMonth)
	{
		//日线，周线，月线;
		return boost::str(table_name_fmt % inst_id % (ktype/ktypeDay) % "kdday");
	}
	else
	{
		//年线;
		return boost::str(table_name_fmt % inst_id % (ktype/ktypeYear) % "kdyear");
	}
	return boost::str(table_name_fmt % inst_id % ktype % "kd");
}

void Sqlite3Store::SetLastError(const char* errmsg/*=nullptr*/, int errcode/*=0*/)
{
	if (!errmsg)
	{
		last_error_msg = "unknown error.";
	}
	else
	{
		last_error_msg = errmsg;
	}
}

bool Sqlite3Store::CreateTables()
{
	char* errmsg = NULL;
	int res = sqlite3_exec(mInstDB, sql_create_exchange, NULL, NULL, &errmsg);
	if (SQLITE_OK != res)
	{
		SetLastError(errmsg, res);
		return false;
	}
	res = sqlite3_exec(mInstDB, sql_create_code_table, NULL, NULL, &errmsg);
	if (SQLITE_OK != res)
	{
		SetLastError(errmsg, res);
		return false;
	}
	res = sqlite3_exec(mInstDB, sql_create_table_instruments, NULL, NULL, &errmsg);
	if (SQLITE_OK != res)
	{
		SetLastError(errmsg,res);
		return false;
	}
	return true;
}
